package com.tianji.remark.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.tianji.common.autoconfigure.mq.RabbitMqHelper;
import com.tianji.common.utils.UserContext;
import com.tianji.remark.entity.LikedRecord;
import com.tianji.remark.mapper.LikedRecordMapper;
import com.tianji.remark.pojo.dto.LikeRecordFormDTO;
import com.tianji.remark.service.ILikedRecordService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.connection.StringRedisConnection;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;

import static com.tianji.common.constants.RedisConstants.LIKE_RECORD_PREFIX;
import static com.tianji.common.constants.RedisConstants.LIKE_TIMES_PREFIX;

/**
 * <p>
 * 点赞记录表 服务实现类
 * </p>
 *
 * @author xjs
 */
@Service
public class LikedRecordServiceImpl2 extends ServiceImpl<LikedRecordMapper, LikedRecord> implements ILikedRecordService {

    @Autowired
    private RabbitMqHelper mqHelper;

    @Autowired
    private StringRedisTemplate redisTemplate;

    @Override
    public List<String> listLikeRecords(List<Long> bizIds, String bizType) {
        List<String> result = new ArrayList<>();
        // 获取用户
        Long userId = UserContext.getUser();
        // 遍历redis中的set
//        for (Long bizId : bizIds) {
//            String likeRecordKey = likeRecordKey(bizType, bizId);
//            Boolean isMember = redisTemplate.opsForSet().isMember(likeRecordKey, userId);
//            if(isMember){
//                result.add(""+bizId);
//            }
//        }
        // 返回值代表的是：多个redis的操作指令，每一个执行的返回值
        List<Object> objects = redisTemplate.executePipelined(new RedisCallback<Object>() {
            @Override
            public Object doInRedis(RedisConnection connection) throws DataAccessException {
                StringRedisConnection redisConnection = (StringRedisConnection)connection;
                // 在这个方法中，把多个redis的操作指令打包一起作为一批发送给redis的服务器，一块来执行
                for (Long bizId : bizIds) {
                    String likeRecordKey = likeRecordKey(bizType, bizId);
                    redisConnection.sIsMember(likeRecordKey, ""+userId);
                }
                return null;
            }
        });
        // 拼装结果集
        for (int i=0; i<bizIds.size(); i++) {
            // 获取第i条指令的执行返回结果
            Object redisReturn = objects.get(i);
            // 如果返回的是true，就说明bizId存在
            if(Boolean.valueOf(redisReturn.toString())){
                result.add(bizIds.get(i)+"");
            }
        }
        return result;

    }

    /**
     * 点赞记录缓存Set
     * key： bizType_bizId
     * value：{userId1， userId2}
     *
     * 点赞数量缓存ZSet
     * key：  bizType
     * value：bizId
     * score：likedTimes
     * */
    @Override
    public void likeOrUnlike(LikeRecordFormDTO dto) {
        // 获取用户
        Long userId = UserContext.getUser();
        // 判断是否是点赞
        Boolean liked = dto.getLiked();
        if(liked){
            String likeRecordKey = likeRecordKey(dto.getBizType(), dto.getBizId());
            // 向redis的set中添加userId
            Long added = redisTemplate.opsForSet().add(likeRecordKey, "" + userId);
            // 添加成功
            if(added > 0){
                // 统计总的点赞数量
                Long likedTimes = redisTemplate.opsForSet().size(likeRecordKey);
                // 写入zset
                String likeTimesKey = likeTimesKey(dto.getBizType());
                redisTemplate.opsForZSet().add(likeTimesKey, dto.getBizId()+"", likedTimes.doubleValue());
            }else{
                // 添加失败了，重复点赞
            }
        }else{
            String likeRecordKey = likeRecordKey(dto.getBizType(), dto.getBizId());
            // set中是否存在userId
            Boolean isMember = redisTemplate.opsForSet().isMember(likeRecordKey, "" + userId);
            if(isMember){
                // 说明点赞记录已经存在，删掉userId
                redisTemplate.opsForSet().remove(likeRecordKey, ""+userId);
                // 统计总的点赞数量
                Long likedTimes = redisTemplate.opsForSet().size(likeRecordKey);
                // 写入zset
                String likeTimesKey = likeTimesKey(dto.getBizType());
                redisTemplate.opsForZSet().add(likeTimesKey, dto.getBizId()+"", likedTimes.doubleValue());
            }else{
                // 说明之前就没点过赞，现在还要取消点赞，结束
            }
        }
    }

    /**
     * 点赞记录使用的数据结构是set
     * */
    private String likeRecordKey(String bizType, Long bizId){
        return LIKE_RECORD_PREFIX + bizType+"_"+bizId;
    }

    /**
     * 点赞次数使用的数据结构是zset
     * */
    public String likeTimesKey(String bizType){
        return LIKE_TIMES_PREFIX + bizType;
    }
}
